package com.iplay.service.notification.storage;

import java.text.ParseException;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import com.iplay.component.date.FeastBookingDateFormatter;
import com.iplay.dao.notification.NotificationDAO;
import com.iplay.dto.notification.NotificationDTO;
import com.iplay.entity.notification.NotificationDO;
import com.iplay.vo.message.MessageVO;

@Service
public class NotificationStorageServiceImpl implements NotificationStorageService {

	@Autowired
	private FeastBookingDateFormatter formatter;

	@Autowired
	private NotificationDAO notficationDAO;

	@Override
	public List<NotificationDTO> saveMessages(List<MessageVO> messages) {
		List<NotificationDO> nos = messages.stream().map(vo -> {
			try {
				return new NotificationDO(vo.getFrom(), vo.getMessage(),
						formatter.parseToTime(formatter.getNotificationCreatedTimeFormat(), vo.getCreatedTime()),
						vo.getRead() > 0);
			} catch (ParseException e) {
				e.printStackTrace();
				return null;
			}
		}).filter(n -> n != null).collect(Collectors.toList());
		Iterator<NotificationDO> iter = notficationDAO.save(nos).iterator();
		List<NotificationDTO> result = new LinkedList<>();
		while (iter.hasNext()) {
			result.add(do2DTO(iter.next()));
		}
		return result;
	}

	@Override
	public Page<NotificationDTO> listNotifications(Boolean read, Pageable pageable) {
		Page<NotificationDTO> result = null;
		if (read == null) {
			result = notficationDAO.findAll(pageable).map(n -> do2DTO(n));
		} else {
			result = notficationDAO.findByStatus(read, pageable).map(n -> do2DTO(n));
		}
		return result;
	}

	@Override
	public int countRead(Boolean read) {
		if (read == null)
			return (int) notficationDAO.count();
		return notficationDAO.countRead(read);
	}

	@Override
	public boolean setRead(int id, boolean read) {
		notficationDAO.updateRead(id, read);
		return true;
	}

	private NotificationDTO do2DTO(NotificationDO notificationDO) {
		return new NotificationDTO(notificationDO.getId(), notificationDO.getFrom(), notificationDO.getMessage(),
				formatter.toNotificationCreatedTime(notificationDO.getCreatedTime()), notificationDO.isRead() ? 1 : 0);

	}

	@Override
	public Optional<NotificationDTO> findById(int id) {
		NotificationDO n = notficationDAO.findOne(id);
		if(n == null)
			return Optional.empty();
		return Optional.of(do2DTO(n));
	}

}
